package com.za.plugin.transfer.func;

import com.za.plugin.pojo.Content;
import com.za.plugin.util.StrUtil;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 解决 find_in_set(.*?) [and|or] find_in_set(.*?) [and|or] find_in_set...  在达梦的问题
 */
public class FindInSetFormTransfer implements FunctionTransfer {
    Pattern compile = Pattern.compile("find_in_set(.*?)\\s+[and|or|AND|OR]+\\s+find_in_set");

    @Override
    public boolean isSupport(String sql) {
        return compile.matcher(sql.toLowerCase()).find();
    }

    // 把  find_in_set(.*?) [and|or] find_in_set(.*?) [and|or] find_in_set... 放在 if() 里
    @Override
    public String transfer(String sql) {
        Matcher matcher = compile.matcher(sql);
        int start = 0, end;
        int left = 0;
        StringBuilder sb = new StringBuilder();
        boolean isMatch = matcher.find();
        if (isMatch) {
            start = matcher.start();
        }
        while (isMatch) {
            end = findValidEnd(sql, start);
            sb.append(sql.substring(left, start)).append(" case when ")
                    .append(sql.substring(start, end)).append(" then true else false end ");
//            sb.append(sql.substring(left, start)).append("if(")
//                    .append(sql.substring(start, end)).append(",true,false) ");
            matcher = compile.matcher(sql.substring(end));
            isMatch = matcher.find();
            if (isMatch && end < sql.length()) {
                start = matcher.start() + end;
                left = end;
            } else if (end < sql.length()) {
                sb.append(sql.substring(end));
            }
        }
        return sb.toString();

//        下面的代码只支持固定数量的 find_in_set, 可以参考
//        Pattern compile = Pattern.compile("(.*?)find_in_set\\((.*?)\\)\\s+([and|or]+)\\s+find_in_set\\((.*?)\\)(.*?)");
//        Matcher matcher = compile.matcher(sql.toLowerCase());
//        StringBuilder sb = new StringBuilder();
//        if (matcher.find()) {
//            sb.append(matcher.group(1)).append(" if(find_in_set(").append(matcher.group(2))
//                    .append(") ").append(matcher.group(3)).append(" find_in_set(").append(matcher.group(4)).append("),true,false) ")
//                    .append(matcher.group(5));
//        }
//        return sb.toString();
//        return sql;
    }

    private static int findValidEnd(String sql, int start) {
        int idx = sql.indexOf("(", start);
        Content expectContent = StrUtil.getExpectContent(sql, idx);
        assert expectContent != null;
        int end = expectContent.getEnd();
        while (end < sql.length() && sql.charAt(end) == ' ') {
            end++;
        }
        String substring = sql.substring(end);
        Pattern compile = Pattern.compile("^[and|or]+\\s+find_in_set");
        if (compile.matcher(substring).find()) {
            if (substring.startsWith("and")) {
                return findValidEnd(sql, end + 3);
            } else if (substring.startsWith("or")) {
                return findValidEnd(sql, end + 2);
            }
        }
        return end;
    }
}
